package org.timemachine.generator;

import java.util.HashMap;
import java.util.Map;

import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtField;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.MemberValue;
import javassist.bytecode.annotation.StringMemberValue;

import org.timemachine.factory.EnumMemberValueFactory;
import org.timemachine.generator.spi.AnnoGenerator;

public class AnnoGeneratorImpl implements AnnoGenerator {

	
	public void createChangeClassAnnoAttr(CtClass cc) {
//		String tableName = JoinTable annoJoinTable;
		String tableName = cc.getSimpleName();
		AnnotationsAttribute attr = (AnnotationsAttribute) new AnnotationsAttribute(cc.getClassFile().getConstPool(), AnnotationsAttribute.visibleTag);		
		Annotation[] annos = new Annotation[3];
		
		Map<String, MemberValue> annoTableMap = new HashMap<String, MemberValue>();
		annoTableMap.put("name", new StringMemberValue(tableName, cc.getClassFile().getConstPool()));
		AnnoGenerator annoGenerator = new AnnoGeneratorImpl();
		annos[0] = annoGenerator.createAnnotation(cc.getClassFile().getConstPool(), "javax.persistence.Table", annoTableMap);
		annos[1] = annoGenerator.createAnnotation(cc.getClassFile().getConstPool(), "javax.persistence.Entity", null);
		annos[2] = annoGenerator.createAnnotation(cc.getClassFile().getConstPool(), "javax.persistence.ExcludeDefaultListeners", null);
		
		attr.setAnnotations(annos);
		cc.getClassFile().addAttribute(attr);
	}
	
	public Annotation createAnnotation(ConstPool cp, String ann, Map<String, MemberValue> params) {

		Annotation idAnn = new Annotation(ann, cp);

		if (params != null) {
			for (Map.Entry<String, MemberValue> entry : params.entrySet()) {
				idAnn.addMemberValue(entry.getKey(), entry.getValue());
			}
		}

		return idAnn;
	}
	
	public void createManyToOneAnno(CtField ctField) throws CannotCompileException {
		AnnotationsAttribute attr = new AnnotationsAttribute(ctField.getFieldInfo().getConstPool(), AnnotationsAttribute.visibleTag);
		Map<String, MemberValue> map = new HashMap<String, MemberValue>();
		//map.put("cascade", EnumMemberValueFactory.getNewInstance(ctField.getFieldInfo().getConstPool(),"javax.persistence.CascadeType","ALL"));
		attr.addAnnotation(createAnnotation(ctField.getFieldInfo().getConstPool(), "javax.persistence.ManyToOne", map));
		ctField.getFieldInfo().addAttribute(attr);
	}
	
	public void createChangeIdAnnoAttr(CtField changeIdField) {
		AnnotationsAttribute attr = new AnnotationsAttribute(changeIdField.getFieldInfo().getConstPool(), AnnotationsAttribute.visibleTag);
		Map<String, MemberValue> annoGeneratedMap = new HashMap<String, MemberValue>();
		annoGeneratedMap.put("strategy", EnumMemberValueFactory.getNewInstance(changeIdField.getFieldInfo().getConstPool(),"javax.persistence.GenerationType","SEQUENCE"));
		
		Map<String, MemberValue> annoColumnMap = new HashMap<String, MemberValue>();
		annoColumnMap.put("name", new StringMemberValue("CHANGE_ID",changeIdField.getFieldInfo().getConstPool()));
		
		attr.addAnnotation(createAnnotation(changeIdField.getFieldInfo().getConstPool(), "javax.persistence.GeneratedValue", annoGeneratedMap));
		attr.addAnnotation(createAnnotation(changeIdField.getFieldInfo().getConstPool(), "javax.persistence.Id", null));
		attr.addAnnotation(createAnnotation(changeIdField.getFieldInfo().getConstPool(), "javax.persistence.Column", annoColumnMap));
		changeIdField.getFieldInfo().addAttribute(attr);
	}
	
	
}
